let optimisme = 0.95 (* optimisme est (la probabilité de réussir) (à dépasser) (pour prendre) *)

(* let vraisemblance_maximale = ref 0. *)
		  
let vraisemblable cartes enchere = (* Le jeu du preneur est-il vraisemblable ? *)
  let nombre_bouts =
    List.length
      (List.filter (Carte.est_bout) cartes)
  in
  let nombre_rois =
    List.length
      (List.filter (Carte.est_roi) cartes)
  in
  let nombre_atouts =
    List.length
      (List.filter (Carte.est_atout) cartes)
  in
  let nombre_coupes =
    let couleurs_coupees =
      ref
	[Carte.Coeur ;
	 Carte.Pique ;
	 Carte.Carreau ;
	 Carte.Trefle] in
    let ajouter (_, c) =
      couleurs_coupees := List.filter
			      ((<>) c)
			      !couleurs_coupees
    in
    let () = List.iter (ajouter) cartes in
    List.length !couleurs_coupees
  in
  let vraisemblance_bouts =
    match enchere, nombre_bouts with
    | (1, 1) -> 5.
    | (1, 2) -> 3.
    | (1, 0) -> 2.
    | (1, 3) -> 1.
    | (2, 0) -> 0.
    | (2, 1) -> 3.
    | (2, 2) -> 4.
    | (2, 3) -> 2.
    | (3, 0) -> 0.
    | (3, 1) -> 0.1
    | (3, 2) -> 2.
    | (3, 3) -> 4.
    | (4, 0) -> 0.
    | (4, 1) -> 0.01
    | (4, 2) -> 2.
    | (4, 3) -> 4.
    | _ -> failwith "Ne peut arriver"
  in
  let vraisemblance_rois =
    match enchere, nombre_rois with
    | (_, 0) -> 1.
    | (_, 1) -> 3.
    | (_, 2) -> 1.
    | (_, 3) -> 1.
    | (_, 4) -> 0.5
    | _ -> failwith "Ne peut arriver"
  in
  let vraisemblance_atouts =
    match enchere with
    | 1 when nombre_atouts >= 3 && nombre_atouts <= 5 -> 3.
    | 1 when nombre_atouts >= 2 && nombre_atouts <= 6 -> 2.
    | 1 -> 1.
    | 2 when nombre_atouts >= 4 && nombre_atouts <= 6 -> 3.
    | 2 when nombre_atouts >= 3 && nombre_atouts <= 7 -> 2.
    | 2 -> 1.
    | 3 when nombre_atouts >= 5 && nombre_atouts <= 7 -> 3.
    | 3 when nombre_atouts >= 4 && nombre_atouts <= 8 -> 2.
    | 3 -> 1.
    | 4 when nombre_atouts >= 6 && nombre_atouts <= 8 -> 3.
    | 4 when nombre_atouts >= 5 && nombre_atouts <= 9 -> 2.
    | 4 -> 1.
    | _ -> failwith "Ne peut arriver"
  in
  let vraisemblance_coupes =
    match enchere, nombre_coupes with
    | (1, 0) -> 2.
    | (1, 1) -> 4.
    | (1, _) -> 0.
    | (2, 0) -> 0.
    | (2, 1) -> 4.
    | (2, 2) -> 3.
    | (2, _) -> 0.
    | (_, 1) -> 2.
    | (_, 2) -> 4.
    | (_, 3) -> 0.5
    | (_, _) -> 0.
  in
  let points =
    epsilon_float
    +. vraisemblance_bouts
    +. vraisemblance_rois
    +. vraisemblance_atouts
    +. vraisemblance_coupes
  in
  let res = (points *. 0.5) +. (1. *. 0.5) (* diminue l'importance de la vraisemblance *) in
  (* let () = *)
  (*   if res > !vraisemblance_maximale then *)
  (*     let () =  vraisemblance_maximale := res in *)
  (*     Printf.printf "Vraisemblance maximale : %f.\n%!" res *)
  (* in *)
  res
    
let list_map fonction =
  let rec aux reste = function
    | [] -> List.rev reste
    | a :: b -> aux ((fonction a) :: reste) b
  in
  aux []

let prendre ?(afficher=false)
	    ?(tictoc1=(ignore, ignore))
	    ?(tictoc2=(ignore, ignore))
	    client =
  let resultats = Array.make 78 (0., 0., 0., 0.) in (* Nombre de tests, points, bouts par carte, nombre de fois où ça passe *)
  let appelables = Array.of_list
		     (Tarotv.cartes_appelables client) in
  let i_test = ref 0 in
  let mon_numero =
    match Tarotv.mon_numero client with
    | None -> failwith "Ne peut arriver"
    | Some n -> n
  in
  let travailler () =
    try
      let carte_appelee = appelables.(!i_test) in
      let () = i_test := (!i_test + 1) mod (Array.length appelables) in
      let () = (fst tictoc1) () in
      let distribution =
	Array.map
	  (List.map
	     (Carte.carte_of_int))
	  (Completer_distribution.completer_distribution
	     15 (Tarotv.interdictions client))
      in
      let () = (snd tictoc1) () in
      let joueur_appele =
	let j = ref mon_numero in
	let () =
	  Array.iteri
	    (fun joueur main ->
	     if joueur < 5 && List.exists ((=) carte_appelee) main
	     then j := joueur)
	    distribution
	in
	!j
      in
      let () =
	if afficher then
	  let interdit = Tarotv.interdictions client in
	  let () = Printf.printf "Dois-je prendre en appelant la carte %s ?\nVoici une distribution possible :\nCœurs         Piques        Carreaux      Trèfles       Atouts        Excuse\n         1             1             1             1             111111111122  \n1234567890VCDR1234567890VCDR1234567890VCDR1234567890VCDR123456789012345678901E\n"
				 (Carte.string_of_carte carte_appelee) in
	  let () =
	    for joueur = 0 to 4 do
	      for carte = 0 to 77 do
		if List.exists ((=) (Carte.carte_of_int carte))
			       distribution.(joueur) then
		  print_char 'o'
		else if interdit.(joueur).(carte) then
		  print_char 'X'
		else print_char ' '
	      done ;
	      if joueur = mon_numero then
		print_string ", moi" ;
	      if joueur = joueur_appele then
		print_string ", appelé" ;
	      print_newline ()
	    done
	  in
	  ()
      in
      let () = (fst tictoc2) () in
      let (nombre_dp, nombre_bouts) =
	Finir_partie.finir_partie
	  ~verbeux:afficher
	  distribution
	  mon_numero
	  joueur_appele
	  None
	  (Array.make 5 None) in
      let () = (snd tictoc2) () in
      let nombre_dp = nombre_dp.(mon_numero) in
      let nombre_bouts = nombre_bouts.(mon_numero) in
      let barre =
	match nombre_bouts with
	| 0 -> 56 * 2
	| 1 -> 51 * 2
	| 2 -> 41 * 2
	| 3 -> 36 * 2
	| x ->
	   let () = Printf.printf "%d : impossible.\n%!" x in
	   failwith "Impossible"
      in
      let () =
	if afficher then
	  Printf.printf "points : %d%s ; bouts : %d. %s.\n%!"
			(nombre_dp / 2) (if nombre_dp mod 2 = 0
					 then "" else ",5")
			nombre_bouts (if nombre_dp > barre then "Ça passe"
				      else "Ça ne passe pas")
      in
      let i_carte_appelee = Carte.int_of_carte carte_appelee in
      let points = (float_of_int nombre_dp) /. 2. in
      let bouts = float_of_int nombre_bouts in
      let (n, p, b, ok) = resultats.(i_carte_appelee) in
      let () =
	resultats.(i_carte_appelee) <-
	  (n +. 1.,
	   p +. points,
	   b +. bouts,
	   ok +. (if nombre_dp > barre then 1. else 0.))
      in
      ()
    with Completer_distribution.Mal_parti ->
      let () = i_test := (!i_test - 1 + Array.length appelables) mod (Array.length appelables) in
      ()
  in
  let exploiter_resultats () =
    let tableau_scores =
      Array.map
	(fun (n, _, _, ok) ->
	 if n = 0. then -.1.
	 else ok /. n)
	resultats
    in
    let i_meilleur =
      let j = ref 0 in
      let () =
	for i=1 to -1 + Array.length tableau_scores do
	  if tableau_scores.(i) > tableau_scores.(!j) then
	    j := i
	done
      in
      !j
    in
    let carte_appelee = Carte.carte_of_int i_meilleur in
    let (n, points, bouts, ok) = resultats.(i_meilleur) in
    let points = points /. n in
    let bouts = bouts /. n in
    let ok = ok /. n in
    (carte_appelee, ok, points, bouts)
  in
  (travailler, exploiter_resultats)

module EcartEffectif = Ecart.Make (Carte)

let rec combinaisons n liste =
  match n with
  | 0 -> [[]]
  | _ ->
     match liste with
     | [] -> []
     | a :: b ->
	let combi_avec_a = combinaisons (n - 1) b in
	let combi_avec_a = List.map
			     (fun combi -> a :: combi)
			     combi_avec_a in
	let combi_sans_a = combinaisons n b in
	combi_avec_a @ combi_sans_a
			 
let ecarter ?(afficher=false)
	    ?(tictoc1=(ignore, ignore))
	    ?(tictoc2=(ignore, ignore))
	    client =
  let main = Tarotv.mon_jeu client in
  let structure = EcartEffectif.structure_ecart
		    main in
  let ecarts_possibles =
    match structure with
    | EcartEffectif.Parmi (n, liste) ->
       Array.of_list (combinaisons n liste)
    | EcartEffectif.ToutesEt
	(obligatoires,
	 EcartEffectif.Parmi (n, possibles)) ->
       Array.of_list
	 (List.map
	    (fun combi -> obligatoires @ combi)
	    (combinaisons n possibles))
    | _ -> failwith "Structure d'écart mal formée"
  in
  let resultats = Array.make (Array.length ecarts_possibles) (0., 0.) in (* n, points *)
  let swap_ecart i j =
    let tmp = ecarts_possibles.(i) in
    let () = ecarts_possibles.(i) <- ecarts_possibles.(j) in
    ecarts_possibles.(j) <- tmp
  in
  let inserer_ecart i =
    let j = Random.int (i + 1) in
    swap_ecart i j
  in
  let () =
    for i = 1 to -1 + Array.length ecarts_possibles do
      inserer_ecart i
    done
  in
  let carte_appelee =
    match Tarotv.carte_appelee client with
    | None -> failwith "Ne peut vraiment pas arriver"
    | Some carte -> carte
  in
  let i_test = ref 0 in
  let mon_numero =
    match Tarotv.mon_numero client with
    | None -> failwith "Ne peut arriver"
    | Some n -> n
  in
  let travailler () =
    try
      let i_ecart = !i_test in
      let ecart = ecarts_possibles.(i_ecart) in
      (* On adapte les interdictions : en effet, on connaît l'écart *)
      let interdictions = Array.make_matrix 6 78 false in
      let () =
	(* On interdit toutes les cartes pour le chien *)
	for j = 0 to -1 + Array.length interdictions.(5) do
	  interdictions.(5).(j) <- true
	done
      in
      let () =
	(* Chaque carte de l'écart est interdite pour tout le monde, sauf le chien. *)
	List.iter
	  (fun carte ->
	   let j = Carte.int_of_carte carte in
	   let () =
	     for i = 0 to -1 + Array.length interdictions
	     do interdictions.(i).(j) <- true done
	   in
	   interdictions.(5).(j) <- false
	  )
	  ecart
      in
      let main =
	List.filter
	  (fun carte_en_main ->
	   not (List.exists ((=) carte_en_main) ecart))
	  main
      in
      let () =
	(* Je m'interdis toutes les cartes *)
	for j = 0 to 77 do
	  interdictions.(mon_numero).(j) <- true
	done
      in
      let () =
	(* Je m'autorise toutes mes cartes restantes et je les interdis pour tout le monde (sauf moi, donc) *)
	List.iter
	  (fun carte ->
	   let j = Carte.int_of_carte carte in
	   for i = 0 to -1 + Array.length interdictions do
	     interdictions.(i).(j) <- true
	   done ;
	   interdictions.(mon_numero).(j) <- false)
	  main
      in
      let () = i_test := (!i_test + 1) mod (Array.length ecarts_possibles) in
      let () = (fst tictoc1) () in
      let distribution =
	Array.map
	  (List.map
	     (Carte.carte_of_int))
	  (Completer_distribution.completer_distribution
	     15 interdictions)
      in
      let () = (snd tictoc1) () in
      let joueur_appele =
	let j = ref mon_numero in
	let () =
	  Array.iteri
	    (fun joueur main ->
	     if joueur < 5 && List.exists ((=) carte_appelee) main
	     then j := joueur)
	    distribution
	in
	!j
      in
      let () =
	if afficher then
	  let interdit = interdictions in
	  let (a, b, c) =
	    match ecart with
	    | [a ; b ; c] ->
	       (Carte.string_of_carte a, Carte.string_of_carte b, Carte.string_of_carte c)
	    | _ -> failwith "Impossible"
	  in
	  let () = Printf.printf "Dois-je écarter %s, %s et %s ?\nVoici une distribution possible :\nCœurs         Piques        Carreaux      Trèfles       Atouts        Excuse\n         1             1             1             1             111111111122  \n1234567890VCDR1234567890VCDR1234567890VCDR1234567890VCDR123456789012345678901E\n"
				 a b c in
	  let () =
	    for joueur = 0 to 4 do
	      for carte = 0 to 77 do
		if List.exists ((=) (Carte.carte_of_int carte))
			       distribution.(joueur) then
		  print_char 'o'
		else if interdit.(joueur).(carte) then
		  print_char 'X'
		else print_char ' '
	      done ;
	      if joueur = mon_numero then
		print_string ", moi" ;
	      if joueur = joueur_appele then
		print_string ", appelé" ;
	      print_newline ()
	    done
	  in
	  ()
      in
      let () = (fst tictoc2) () in
      let (nombre_dp, nombre_bouts) = Finir_partie.finir_partie
					~verbeux:afficher
					distribution
					mon_numero
					joueur_appele
					None
					(Array.make 5 None) in
      let () = (snd tictoc2) () in
      (* Je tiens compte de l'écart *)
      let nombre_dp = List.fold_left
			(fun score carte -> score + Carte.demipoints carte)
			(nombre_dp.(mon_numero))
			ecart in
      let nombre_bouts = nombre_bouts.(mon_numero) in
      let () =
	if afficher then
	  Printf.printf "points : %d%s ; bouts : %d.\n%!"
			(nombre_dp / 2) (if nombre_dp mod 2 = 0
					 then "" else ",5")
			nombre_bouts 
      in
      let points = (float_of_int nombre_dp) /. 2. in
      (* let points = *)
      (* 	let barre = *)
      (* 	  match nombre_bouts with *)
      (* 	  | 0 -> 56 *)
      (* 	  | 1 -> 51 *)
      (* 	  | 2 -> 41 *)
      (* 	  | 3 -> 36 *)
      (* 	  | _ -> failwith "Barre incalculable" *)
      (* 	in *)
      (* 	let dp_barre = barre * 2 in *)
      (* 	let ok = nombre_dp >= dp_barre in *)
      (* 	let dp_score = *)
      (* 	  if ok then +50 else -50 in *)
      (* 	let dp_score = dp_score + nombre_dp - barre in *)
      (* 	let score = if dp_score mod 2 = 0 then dp_score / 2 *)
      (* 		    else if ok then (dp_score / 2) + 1 *)
      (* 		    else dp_score / 2 in *)
      (* 	let score = *)
      (* 	  match contrat with *)
      (* 	  | 1 -> score *)
      (* 	  | 2 -> 2 * score *)
      (* 	  | 3 -> 4 * score *)
      (* 	  | 4 -> 6 * score *)
      (* 	  | _ -> failwith "Contrat impossible" *)
      (* 	in *)
      (* 	let empoches = 2 * score (\* Je suis l'attaquant *\) in *)
      (* 	float_of_int empoches *)
      (* in *)
      let (n, p) = resultats.(i_ecart) in
      let n = n +. 1. in
      let p = p +. points in
      let () = resultats.(i_ecart) <- (n, p) in
      ()
    with Completer_distribution.Mal_parti ->
      let () =
	i_test :=
	  (!i_test - 1 + Array.length ecarts_possibles)
	  mod (Array.length ecarts_possibles) in
      ()
  in
  let exploiter_resultats () =
    let scores = Array.map (fun (n, p) ->
			    if n = 0. then -.max_float
			    else p /. n)
			   resultats in
    let i_meilleur =
      let j = ref 0 in
      let () =
	for i = 1 to -1 + Array.length scores do
	  if scores.(i) > scores.(!j) then
	    j := i
	done
      in
      !j
    in
    let meilleur_ecart = ecarts_possibles.(i_meilleur) in
    let (n, p) = resultats.(i_meilleur) in
    (meilleur_ecart, p /. n)
  in
  (travailler, exploiter_resultats, Array.length ecarts_possibles)

let jouer ?(afficher=false)
	  ?(tictoc1=(ignore, ignore))
	  ?(tictoc2=(ignore, ignore))
	  client =
  try
    let resultats = Array.make 78 (0., 0., 0., 0.) in (* n - points - bouts - points empochés *)
    let jouables = Array.of_list
		     (Tarotv.cartes_jouables client) in
    let i_test = ref 0 in
    let couleur_demandee = Tarotv.couleur_demandee client in
    let debut_tapis = Array.make 5 None in
    let nombre_plis_joues = Tarotv.nombre_plis_joues client in
    let interdictions = Tarotv.interdictions client in
    let mon_numero =
      match Tarotv.mon_numero client with
      | None -> failwith "Ne peut arriver"
      | Some n -> n
    in
    let carte_appelee =
      match Tarotv.carte_appelee client with
      | None -> failwith "Bloubloublou"
      | Some c -> c
    in
    let () =
      List.iter
	(fun (i, carte, _) ->
	 if carte <> Carte.fausse_excuse then
	   let j = Carte.int_of_carte carte in
	   (* On remplit le début du tapis... *)
	   let () = debut_tapis.(i) <- Some carte in
	   (* On autorise les cartes déjà jouées. *)
	   interdictions.(i).(j) <- false)
	(Tarotv.repartition_cartes client (Tarotv.nombre_plis_joues client))
    in
    let preneur = match Tarotv.preneur client with None -> failwith "Ne peut arriver"
						 | Some p -> p in
    let (_, contrat) = Tarotv.enchere_maximale client in
    let n_reussis = ref 0 in
    let travailler () =
      try
	let carte_jouee = jouables.(!i_test) in
	(* Si je suis le premier à jouer, je recalcule la couleur demandée *)
	let couleur_demandee =
	  match couleur_demandee with
	  | None ->
	     let couleur = snd carte_jouee in
	     if couleur <> Carte.Excuse then
	       Some couleur
	     else None
	  | Some c -> Some c
	in
	let () = debut_tapis.(mon_numero) <- Some carte_jouee in
	let () = i_test := (!i_test + 1) mod (Array.length jouables) in
	let () = (fst tictoc1) () in
	let distribution =
	  Array.map
	    (List.map
	       (Carte.carte_of_int))
	    (Completer_distribution.completer_distribution
	       (15 - nombre_plis_joues) interdictions)
	in
	let cartes_preneur =
	  let i = -1 + Tarotv.nombre_plis_joues client in
	  let deja_jouees = List.filter
			      (fun (poseur, _, _) ->
			       poseur = preneur)
			      (Tarotv.repartition_cartes client i)
	  in
	  let deja_jouees = List.map (fun (_, c, _) -> c)
				     deja_jouees in
	  let restantes = distribution.(preneur) in
	  deja_jouees @ restantes
	in
	let vraisemblance = vraisemblable cartes_preneur contrat in
	let () = (snd tictoc1) () in
	let joueur_appele =
	  match Tarotv.joueur_appele client with
	  | None ->
	     let j = ref mon_numero in
	     let () =
	       Array.iteri
		 (fun joueur main ->
		  if joueur < 5 && List.exists ((=) carte_appelee) main
		  then j := joueur)
		 distribution
	     in
	     !j
	  | Some j -> j
	in
	let () =
	  if afficher then
	    let interdit = Tarotv.interdictions client in
	    let tapis = Array.make 79 (-1) in
	    let () =
	      List.iter
		(fun (poseur, carte, _) ->
		 tapis.(Carte.int_of_carte carte) <- poseur)
		(Tarotv.repartition_cartes client (Tarotv.nombre_plis_joues client))
	    in
	    let () = tapis.(Carte.int_of_carte carte_jouee) <- mon_numero in
	    let () = Printf.printf "Dois-je jouer la carte %s ?\nVoici une distribution possible :\nCœurs         Piques        Carreaux      Trèfles       Atouts        Excuse\n         1             1             1             1             111111111122  \n1234567890VCDR1234567890VCDR1234567890VCDR1234567890VCDR123456789012345678901E\nElle a une vraisemblance de %f.\n%!"
				   (Carte.string_of_carte carte_jouee) vraisemblance in
	    let () =
	      for joueur = 0 to 5 do
		for carte = 0 to 77 do
		  if List.exists ((=) (Carte.carte_of_int carte))
				 distribution.(joueur) then
		    print_char 'o'
		  else if interdit.(joueur).(carte) then
		    print_char 'X'
		  else print_char ' '
		done ;
		if joueur = preneur then
		  print_string ", preneur" ;
		if joueur = mon_numero then
		  print_string ", moi" ;
		if joueur = joueur_appele then
		  print_string ", appelé" ;
		if joueur = 5 then
		  print_string ", chien" ;
		print_newline ()
	      done
	    in
	    let () = Array.iter
		       (fun p -> if p >= 0 then print_int p else print_char ' ')
		       tapis in
	    let () = print_newline () in
	    let () =
	      Printf.printf
		"%s%s\n%!"
		(String.make
		   (match couleur_demandee with
		    | Some Carte.Coeur -> 0
		    | Some Carte.Pique -> 14
		    | Some Carte.Carreau -> 28
		    | Some Carte.Trefle -> 42
		    | Some Carte.Atout -> 56
		    | Some Carte.Excuse -> 77
		    | None -> 0) ' ')
		(String.make
		   (match couleur_demandee with
		    | Some Carte.Atout -> 21
		    | Some Carte.Excuse -> 1
		    | Some _ -> 14
		    | None -> 0) '-')
	    in
	    ()
	in
	let () = (fst tictoc2) () in
	let (nombre_dp, nombre_bouts) =
	  try
	    Finir_partie.finir_partie
	      ~verbeux:afficher
	      distribution
	      preneur
	      joueur_appele
	      couleur_demandee
	      debut_tapis
	  with
	  | Failure str -> let () = Printf.printf "Échec : %s.\n%!" str in
			   failwith "échec"
	  | exn -> let () = Printf.printf "Échec...\n%!" in
		   raise exn
	in
	let () = (snd tictoc2) () in
	let (dp_gagnes, bouts_remportes) = Tarotv.points client (Some joueur_appele) in
	let nombre_dp = nombre_dp.(mon_numero) + dp_gagnes in
	let nombre_bouts = nombre_bouts.(mon_numero) + bouts_remportes in
	let () =
	  if afficher then
	    Printf.printf "points : %d%s ; bouts : %d.\n%!"
			  (nombre_dp / 2) (if nombre_dp mod 2 = 0
					   then "" else ",5")
			  nombre_bouts 
	in
	let points_empoches =
	  let signe_score =
	    if mon_numero = preneur then 2
	    else if mon_numero = joueur_appele then 1
	    else -1
	  in
	  let facteur_mult = match contrat with
	    | 1 -> 1
	    | 2 -> 2
	    | 3 -> 4
	    | 4 -> 6
	    | _ -> failwith "Mauvais contrat"
	  in
	  let pab = 0 (* Il faut adapter finir_partie *) (* 10 ou -10 ou 0 *) in
	  let bouts_preneur =
	    if mon_numero = preneur || mon_numero = joueur_appele then
	      nombre_bouts
	    else 3 - nombre_bouts
	  in
	  let dp_preneur =
	    if mon_numero = preneur || mon_numero = joueur_appele then
	      nombre_dp
	    else 182 - nombre_dp (* 91 points *)
	  in
	  let points_barre = match bouts_preneur with
	    | 0 -> 56
	    | 1 -> 51
	    | 2 -> 41
	    | 3 -> 36
	    | _ -> failwith "Le preneur a plus de 3 bouts."
	  in
	  let ok = dp_preneur >= 2 * points_barre in
	  let dp_score =
	    if ok then 50 else -50 in
	  let dp_score = dp_score + dp_preneur - points_barre in
	  let score = if dp_score mod 2 = 0 then dp_score / 2
		      else if ok then 1 + dp_score / 2
		      else dp_score / 2 in
	  let score = score + pab in
	  let score = facteur_mult * score in
	  let empoches = signe_score * score in
	  float_of_int empoches
	in
	let points = (float_of_int nombre_dp) /. 2. in
	let bouts = float_of_int nombre_bouts in
	let i_jouee = Carte.int_of_carte carte_jouee in
	let (n, p, b, pe) = resultats.(i_jouee) in
	let () =
	  resultats.(i_jouee) <-
	    (n +. vraisemblance,
	     p +. (vraisemblance *. points),
	     b +. (vraisemblance *. bouts),
	     pe +. (vraisemblance *. points_empoches))
	in
	incr n_reussis
      with
	Completer_distribution.Mal_parti ->
	let () =
	  if afficher then
	    Printf.printf "Je suis mal parti pour la distribution.\n%!"
	in
	let () = i_test := (!i_test + (Array.length jouables) - 1)
			   mod (Array.length jouables) in
	()
      | e -> failwith ("Exception dans Decision.jouer (travailler) : "^(Printexc.to_string e))
    in
    let exploiter_resultats () =
      let scores = Array.map
		     (fun (n, _, _, pe) ->
		      if n = 0. then -.max_float
		      else pe /. n)
		     resultats in
      (* let () = *)
      (* 	Array.iteri *)
      (* 	  (fun i_carte (points, bouts) -> *)
      (* 	   Printf.printf "Carte %s : %f points et %f bouts\n%!" *)
      (* 			 (Carte.string_of_carte (Carte.carte_of_int i_carte)) *)
      (* 			 points bouts) *)
      (* 	  tableau_moyennes *)
      (* in *)
      (* Chaque bout compte pour 9 points *)
      let meilleure_carte =
	let c = ref 0 in
	let () =
	  for i=1 to -1 + Array.length scores do
	    if scores.(i) > scores.(!c) then
	      c := i
	  done
	in
	!c
      in
      let (points, bouts, points_empoches) =
	let (n, p, b, pe) = resultats.(meilleure_carte) in
	(p /. n, b /. n, pe /. n)
      in
      let jouee = Carte.carte_of_int meilleure_carte in
      (jouee, points, bouts, points_empoches, !n_reussis)
    in
    (travailler, exploiter_resultats)
  with e ->
    failwith ("Exception dans Decision.jouer : "^(Printexc.to_string e))

